﻿using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JGSY.DotNetty.Common
{
    public static class ObjectExtension
    {
        // 改用 ConcurrentDictionary 支持多线程安全
        private static readonly ConcurrentDictionary<Type, Func<object, object>> ConvertDictionary =
            new ConcurrentDictionary<Type, Func<object, object>>();
        /// <summary>
        /// 注册自定义转换方法
        /// </summary>
        public static void RegisterConverter(Type targetType, Func<object, object> converter)
        {
            ConvertDictionary.AddOrUpdate(targetType, converter, (_, _) => converter);
        }
        static ObjectExtension()
        {
            // 基础类型转换
            RegisterConverter(typeof(bool), WrapValueConvert(Convert.ToBoolean));
            RegisterConverter(typeof(bool?), WrapValueConvert(Convert.ToBoolean));
            RegisterConverter(typeof(int), WrapValueConvert(Convert.ToInt32));
            RegisterConverter(typeof(int?), WrapValueConvert(Convert.ToInt32));
            RegisterConverter(typeof(long), WrapValueConvert(Convert.ToInt64));
            RegisterConverter(typeof(long?), WrapValueConvert(Convert.ToInt64));
            RegisterConverter(typeof(short), WrapValueConvert(Convert.ToInt16));
            RegisterConverter(typeof(short?), WrapValueConvert(Convert.ToInt16));
            RegisterConverter(typeof(double), WrapValueConvert(Convert.ToDouble));
            RegisterConverter(typeof(double?), WrapValueConvert(Convert.ToDouble));
            RegisterConverter(typeof(float), WrapValueConvert(Convert.ToSingle));
            RegisterConverter(typeof(float?), WrapValueConvert(Convert.ToSingle));
            RegisterConverter(typeof(decimal), WrapValueConvert(Convert.ToDecimal));
            RegisterConverter(typeof(decimal?), WrapValueConvert(Convert.ToDecimal));

            // Guid 和 Guid? 特殊处理
            RegisterConverter(typeof(Guid), m => Guid.Parse(m.ToString()));
            RegisterConverter(typeof(Guid?), m => string.IsNullOrEmpty(m?.ToString()) ? null : (object)Guid.Parse(m.ToString()));

            // string 直接转换
            RegisterConverter(typeof(string), m => m?.ToString());

            // DateTime 和 DateTime?
            RegisterConverter(typeof(DateTime), WrapValueConvert(Convert.ToDateTime));
            RegisterConverter(typeof(DateTime?), WrapValueConvert(Convert.ToDateTime));

            // byte[] 转换（支持 Base64 字符串或 hex 字符串）
            RegisterConverter(typeof(byte[]), m =>
            {
                if (m is string str)
                {
                    if (str.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                        return HexStringToBytes(str);
                    else
                        return Convert.FromBase64String(str);
                }
                return m as byte[];
            });
        }
        /// <summary>
        /// Object转换为Json
        /// </summary>
        /// <param name="inputObj"></param>
        /// <returns></returns>
        public static string ToJson(this object inputObj)
        {
            return JsonConvert.SerializeObject(inputObj);
        }
        /// <summary>
        /// 转换为
        /// </summary>
        /// <param name="inputObj"></param>
        /// <param name="targetType"></param>
        /// <returns></returns>
        public static object ConvertTo(this object inputObj, Type targetType)
        {
            if (inputObj == null)
            {
                if (targetType.IsValueType) throw new DotNettyServerException($"不能将null转换为{targetType.Name}");
                return null;
            }
            if (inputObj.GetType() == targetType || targetType.IsInstanceOfType(inputObj))
            {
                return inputObj;
            }
            if (ConvertDictionary.ContainsKey(targetType))
            {
                return ConvertDictionary[targetType](inputObj);
            }
            try
            {
                return Convert.ChangeType(inputObj, targetType);
            }
            catch (Exception ex)
            {
                throw new DotNettyServerException($"未实现到{targetType.Name}的转换方法", ex);
            }
        }
        #region 私有方法
        /// <summary>
        /// 包装值转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="input"></param>
        /// <returns></returns>
        private static Func<object, object> WrapValueConvert<T>(Func<object, T> input) where T : struct
        {
            return i =>
            {
                if (i == null || i is DBNull) return null;
                return input(i);
            };
        }
        /// <summary>
         /// 16 进制字符串转 byte[]（如 "0x010203"）
         /// </summary>
        private static byte[] HexStringToBytes(string hex)
        {
            hex = hex.Substring(2); // 去掉 "0x"
            var bytes = new byte[hex.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
                bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            return bytes;
        }
        #endregion
    }
}
